package com.stars.easyms.alarm.message;

import com.stars.easyms.alarm.bean.EasyMsAlarmTraceInfo;
import com.stars.easyms.alarm.constant.TraceIdTypeEnum;
import com.stars.easyms.alarm.properties.EasyMsAlarmProperties;
import com.stars.easyms.base.util.ApplicationContextHolder;
import com.stars.easyms.base.util.DateTimeUtil;
import org.apache.commons.lang3.StringUtils;

/**
 * <p>className: BaseAlarmMessageMarkdownHandler</p>
 * <p>description: 告警信息markdown处理基础类</p>
 *
 * @author guoguifang
 * @version 1.6.3
 * @date 2020/9/18 3:07 下午
 */
abstract class BaseAlarmMessageMarkdownHandler<T extends EasyMsAlarmTraceInfo> {

    private EasyMsAlarmProperties easyMsAlarmProperties;

    BaseAlarmMessageMarkdownHandler() {
        this.easyMsAlarmProperties = ApplicationContextHolder.getApplicationContext().getBean(EasyMsAlarmProperties.class);
    }

    String handleContext(EasyMsAlarmMessage easyMsAlarmMessage, T traceInfo) {
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("## ").append(easyMsAlarmMessage.getTitle());
        appendRequestInfo(stringBuilder, traceInfo);
        appendAlarmTime(stringBuilder, traceInfo);
        stringBuilder.append(getDetailMessage(traceInfo));
        appendTraceId(stringBuilder, traceInfo);
        appendRequestId(stringBuilder, traceInfo);
        appendAsyncId(stringBuilder, traceInfo);
        return stringBuilder.toString();
    }

    String transferMarkdownCharacter(String sourceStr) {
        return sourceStr.replace("#", "\\#")
                .replace("\\r\\n", "  \\r\\n");
    }

    private void appendRequestInfo(StringBuilder stringBuilder, EasyMsAlarmTraceInfo traceInfo) {
        stringBuilder.append("\n\n**告警系统:** ").append(traceInfo.getApplicationName());
        if (traceInfo.getEnv() != null) {
            stringBuilder.append("\n\n**告警环境:** ").append(traceInfo.getEnv());
        }
        if (StringUtils.isNotBlank(traceInfo.getRequestSys())) {
            stringBuilder.append("\n\n**请求系统:** ").append(traceInfo.getRequestSys());
        }
        if (StringUtils.isNotBlank(traceInfo.getRequestPath())) {
            stringBuilder.append("\n\n**请求地址:** ").append(traceInfo.getRequestPath());
        }
    }

    private void appendAlarmTime(StringBuilder stringBuilder, EasyMsAlarmTraceInfo traceInfo) {
        long alarmTime = traceInfo.getAlarmTime();
        String alarmLocalDateTimeStr = DateTimeUtil.getDatetimeNormalStrWithMills(alarmTime);
        stringBuilder.append("\n\n**告警时间:** ").append(alarmLocalDateTimeStr);
        String alarmBeijingDataTimeStr = DateTimeUtil.getBeijingDateTimeNormalStrWithMills(alarmTime);
        if (!alarmBeijingDataTimeStr.equals(alarmLocalDateTimeStr)) {
            stringBuilder.append("\n\n**北京时间:** ").append(alarmBeijingDataTimeStr);
        }
    }

    abstract String getDetailMessage(T alarmTraceInfo);

    private void appendAsyncId(StringBuilder stringBuilder, EasyMsAlarmTraceInfo traceInfo) {
        String asyncId = traceInfo.getAsyncId();
        if (StringUtils.isNotBlank(asyncId)) {
            stringBuilder.append("\n\n**异步链路ID:** [")
                    .append(asyncId)
                    .append("](")
                    .append(getQueryUrl(traceInfo, asyncId, TraceIdTypeEnum.ASYNC_ID))
                    .append(")");
        }
    }

    private void appendRequestId(StringBuilder stringBuilder, EasyMsAlarmTraceInfo traceInfo) {
        String requestId = traceInfo.getRequestId();
        if (StringUtils.isNotBlank(requestId)) {
            stringBuilder.append("\n\n**请求链路ID:** [")
                    .append(requestId)
                    .append("](")
                    .append(getQueryUrl(traceInfo, requestId, TraceIdTypeEnum.REQUEST_ID))
                    .append(")");
        }
    }

    private void appendTraceId(StringBuilder stringBuilder, EasyMsAlarmTraceInfo traceInfo) {
        String traceId = traceInfo.getTraceId();
        if (StringUtils.isNotBlank(traceId)) {
            stringBuilder.append("\n\n**全链路ID:** [")
                    .append(traceId)
                    .append("](")
                    .append(getQueryUrl(traceInfo, traceId, TraceIdTypeEnum.TRACE_ID))
                    .append(")");
        }
    }

    private String getQueryUrl(EasyMsAlarmTraceInfo traceInfo, String oneId, TraceIdTypeEnum traceIdType) {
        String plumeLogUrl = easyMsAlarmProperties.getPlumeLog().getUrl();
        if (StringUtils.isNotBlank(plumeLogUrl)) {
            return getPlumeLogQueryUrl(traceInfo, oneId, plumeLogUrl, traceIdType);
        }
        return getFullKibanaQueryUrl(traceInfo, oneId, traceIdType);
    }

    private String getPlumeLogQueryUrl(EasyMsAlarmTraceInfo traceInfo, String oneId,
                                       String plumeLogUrl, TraceIdTypeEnum traceIdType) {
        if (TraceIdTypeEnum.ASYNC_ID == traceIdType) {
            return getFormatUrl(plumeLogUrl)
                    + "#/?traceId=" + traceInfo.getTraceId() + "&searchKey=" + oneId
                    + "&time=" + (System.currentTimeMillis() - 86400000) + "," + (System.currentTimeMillis() + 3600000);
        }
        return getFormatUrl(plumeLogUrl)
                + "#/?traceId=" + oneId
                + "&time=" + (System.currentTimeMillis() - 86400000) + "," + (System.currentTimeMillis() + 3600000);
    }

    private String getFullKibanaQueryUrl(EasyMsAlarmTraceInfo traceInfo, String oneId, TraceIdTypeEnum traceIdType) {
        StringBuilder stringBuilder = new StringBuilder();
        String kibanaUrl = easyMsAlarmProperties.getElk().getKibanaUrl();
        if (StringUtils.isNotBlank(kibanaUrl)) {
            long exceptionTime = traceInfo.getAlarmTime();
            String columns = easyMsAlarmProperties.getElk().getColumns();
            stringBuilder.append(getFormatUrl(kibanaUrl))
                    .append("#/discover?_g=(filters:!(),refreshInterval:(pause:!t,value:0),time:(from:'")
                    .append(getKibanaQueryStartTime(exceptionTime))
                    .append("',to:'")
                    .append(getKibanaQueryEndTime(exceptionTime))
                    .append("'))&_a=(columns:!(")
                    .append(StringUtils.isNotBlank(columns) ? columns : "_source")
                    .append("),index:'")
                    .append(getKibanaQueryIndex(traceInfo, traceIdType == TraceIdTypeEnum.TRACE_ID))
                    .append("',interval:auto,query:(language:kuery,query:'")
                    .append(oneId)
                    .append("'),sort:!('@timestamp',asc))");
        }
        return stringBuilder.toString();
    }

    /**
     * 获取kibana查询起始时间，异常发生时间前五分钟开始
     */
    private String getKibanaQueryStartTime(long exceptionTime) {
        return DateTimeUtil.getUTCDateTime(exceptionTime - 300000);
    }

    /**
     * 获取kibana查询结束时间，为保证全链路显示完整，结束时间为异常发生时间后五分钟结束
     */
    private String getKibanaQueryEndTime(long exceptionTime) {
        return DateTimeUtil.getUTCDateTime(exceptionTime + 300000);
    }

    private String getKibanaQueryIndex(EasyMsAlarmTraceInfo traceInfo, boolean isTraceId) {
        String index = null;
        if (isTraceId) {
            index = easyMsAlarmProperties.getElk().getGlobalIndex();
            if (StringUtils.isBlank(index)) {
                index = easyMsAlarmProperties.getElk().getIndex();
            }
        } else {
            if (!traceInfo.isUserDefaultElkIndex()) {
                index = easyMsAlarmProperties.getElk().getIndexs().get(traceInfo.getApplicationName());
            }
            if (StringUtils.isBlank(index)) {
                index = easyMsAlarmProperties.getElk().getIndex();
                if (StringUtils.isBlank(index)) {
                    index = easyMsAlarmProperties.getElk().getGlobalIndex();
                }
            }
        }
        return index == null ? "" : index;
    }

    private String getFormatUrl(String url) {
        return url.endsWith("/") ? url : url + "/";
    }
}
